function LineChart() {
  var margin = {top: 40, right: 40, bottom: 60, left: 40},
      width = 760,
      height = 400,
      xValue = function(d) { return d[0]; },
      yValue = function(d) { return d[1]; },
      xScale = d3.scale.ordinal(),
      yScale = d3.scale.linear(),
      line = d3.svg.line().x(X).y(Y),
      yTitle = "",
      xTitle = "";

	function chart(selection) {
		selection.each(function(data) {
			//Only one series is supported
			data = data[0];
			
			//Extract graph data
			xTitle = data.name;
			yTitle = data.fields[0];
		
			yScale 
			.domain([0, d3.max(data.data, function(d) { return d.fields[yTitle]; })])
			.rangeRound([height - margin.top - margin.bottom, 0])
			.nice();
			
			xScale
			.domain(d3.range(data.data.length))
			.rangeBands([0, width - margin.right - margin.left]);
		  
		  	// Create the svg element
		    var svg = d3.select(this).append('svg');
		   
		  	// Update the outer dimensions.
		 	svg.attr("width", width)
		    .attr("height", height);
			
			svg.append("rect").attr("x",0)
			.attr("y",0)
			.attr("width", width)
			.attr("height", height)
			.attr("class", "chartcontainer");
			
		  	// Otherwise, create the skeletal chart.
		  	var gChart = svg.append("g");
		  	gChart.attr("x", 0)
		  	.attr("y", 0)
		  	.attr("transform", "translate("+margin.left+",0)");
		  	
		  	var gEnter = gChart.append("g");
		  	var gLabels = gChart.append("g");
		  	
		  	
		  	gEnter
		  		.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
		  	
		  	
			//Draw markers and extras			
			
			//Y Label
			gLabels.append("text")
			.attr("transform", "rotate(-90 0 0) translate(-"+height/2+",0)")
			.text(yTitle)
			.classed("title", true);
			
			
			//X Label
			gLabels.append("text")
			.attr("x", ((width-margin.left-margin.right)/2))
			.attr("text-anchor", "middle")
			.attr("y", height - margin.bottom/3)
			.text(xTitle)
			.classed("title", true);
			
			//Relocatable label
			gLabels.append("text")
				.classed("valueLabel", true)
				.attr("x",0)
				.attr("y",0)
				.attr("dx", "1em")
				.text("");
			
			function drawValueLabel(d,i){
				d = d.fields[yTitle];
				
				xoff = xScale(i)
				yoff = yScale(d)-40 < margin.top ? yScale(d)+80 : yScale(d)+20
				
				gLabels.select("text.valueLabel")
				.text(d.toFixed(2))
				.transition()
				.attr("x", xoff )
				.attr("y",  yoff);
				
				gEnter.select(".line")
				.transition()
				.style("opacity", 0.5);
				
				gEnter.selectAll("circle.marker")
				.transition()
				.style("stroke", "none");
				
				d3.select(this)
				.transition()
				.style("stroke", "black")
				.style("stroke-width", 2);
				
				gEnter.selectAll("line.lineind")
				.transition()
				.attr("y1", height-margin.bottom-margin.top)
				.remove();
				
				gEnter.append("line")
				.attr("class", "lineind")
				.attr("x1", xScale(i))
				.attr("x2", xScale(i))
				.attr("y2", height-margin.bottom-margin.top)
				.attr("y1", height-margin.bottom-margin.top)
				.transition()
				.attr("y1", yScale(d)+6)
				
				d3.event.stopImmediatePropagation();
			}
			
			function clearSelection(d,i) {
				gLabels.select("text.valueLabel")
				.transition()
				.attr("x", -20 )
				.attr("y",  -20);
				
				gEnter.select(".line")
				.transition()
				.style("opacity", 1);
				
				gEnter.selectAll("circle.marker")
				.transition()
				.style("stroke", "none");
				
				gEnter.selectAll("line.lineind")
				.transition()
				.attr("y1", height-margin.bottom-margin.top)
				.remove();
			}
			
			svg.on("click", clearSelection);
			
			//Draw vertical guides
			gEnter.selectAll("line.guide")
			.data(data.data)
			.enter().append("line")
			.attr("x1", X)
			.attr("x2", X)
			.attr("y1", 0)
			.attr("y2", height-margin.bottom-margin.top)
			.style("stroke", "#ccc");
			
			
			//Draw horizontal guides
			gEnter.selectAll("line.scale")
			.data(yScale.ticks(10))
			.enter().append("line")
			.attr("x1", 0)
			.attr("x2", xScale.rangeExtent()[1]-xScale.rangeBand() )
			.attr("y1", function(d) { return yScale(d) })
			.attr("y2", function(d) { return yScale(d) })
			.style("stroke", "#ccc");
			
			
			//x Labels
			gEnter.selectAll("text.xlabels")
			.data(data.data)
			.enter().append("text")
			.attr("x", X)
			.attr("y", yScale(0))
			.attr("dy", "+10px") // vertical-align: middle
			.attr("text-anchor", "middle")
			.attr("class", "xlabels")
			.text(function(d,i) { return d.id; });
			
			
			//scale labels
			gEnter.selectAll("text.scale")
			.data(yScale.ticks(10))
			.enter().append("text")
			.attr("x", "-1em")
			.attr("text-anchor", "end")
			.attr("dy", "0.5em")
			.attr("class", "scale")
			.attr("y", function(d) { return yScale(d) })
			.text(String);
			
			
		  	
		  	// Update the line path.
		  	// Update the inner dimensions.
		  	
		  	
		  	gEnter.append("path").attr("class", "line");
		  	gEnter.select(".line")
		     	.attr("d", line(data.data))
		     	.style("fill", "none")
		     	.attr("class", "line");	    
		     	
		    //markers
		    gEnter.selectAll("circle.marker")
		    .data(data.data, function(d) { return d.fields[yTitle]; })
		    .enter().append("circle")
		    .attr("r", 6)
		    .attr("cx", function(d,i) {return xScale(i)})
		    .attr("cy", Y)
		    .on("click", drawValueLabel)
		    .attr("class", "marker")
		    
		});
	}

	// The x-accessor for the path generator
	function X(d, i) {
		return xScale(i);
	}
	
	// The y-accessor for the path generator
	function Y(d) {
		return yScale(d.fields[yTitle]);
	}
	
	chart.margin = function(_) {
		if (!arguments.length) return margin;
		margin = _;
		return chart;
	};
	
	chart.width = function(_) {
		if (!arguments.length) return width;
		width = _;
		return chart;
	};
	
	chart.height = function(_) {
		if (!arguments.length) return height;
		height = _;
		return chart;
	};
	
	chart.x = function(_) {
		if (!arguments.length) return xValue;
		xValue = _;
		return chart;
	};
	
	chart.y = function(_) {
		if (!arguments.length) return yValue;
		yValue = _;
		return chart;
	};

  return chart;
}


function BarChart() {
  var margin = {top: 40, right: 40, bottom: 60, left: 40},
      width = 760,
      height = 400,
      xValue = function(d) { return d[0]; },
      yValue = function(d) { return d.fields[yTitle]; },
      xScale = d3.scale.ordinal(),
      yScale = d3.scale.linear(),
      line = d3.svg.line().x(X).y(Y),
      yTitle = "",
      xTitle = "";

	function chart(selection) {
		selection.each(function(data) {
			//Only one series is supported
			data = data[0];
			
			//Extract graph data
			xTitle = data.name;
			yTitle = data.fields[0];
					
			yScale 
			.domain([0, d3.max(data.data, function(d) { return d.fields[yTitle]; })])
			.rangeRound([height - margin.top - margin.bottom, 0])
			.nice();
			
			xScale
			.domain(d3.range(data.data.length))
			.rangeRoundBands([0, width - 2*margin.left - margin.right], 0);
		  
		  	// Create the svg element
		    var svg = d3.select(this).append('svg');
		   
		  	// Update the outer dimensions.
		 	svg.attr("width", width)
		    .attr("height", height);
			
			svg.append("rect").attr("x",0)
			.attr("y",0)
			.attr("width", width)
			.attr("height", height)
			.attr("class", "chartcontainer");
			
		  	// Otherwise, create the skeletal chart.
		  	var gChart = svg.append("g");
		  	gChart.attr("x", 0)
		  	.attr("y", 0)
		  	.attr("transform", "translate("+margin.left+",0)");
		  	
		  	var gEnter = gChart.append("g");
		  	var gLabels = gChart.append("g");
		  	
		  	gEnter
		  		.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
		  	
			//Draw markers and extras			
			
			//Y Label
			gLabels.append("text")
			.attr("transform", "rotate(-90 0 0) translate(-"+height/2+",0)")
			.text(yTitle)
			.classed("title", true);
			
			
			//X Label
			gLabels.append("text")
			.attr("x", ((width-margin.left-margin.right)/2))
			.attr("text-anchor", "middle")
			.attr("y", height - margin.bottom/3)
			.text(xTitle)
			.classed("title", true);
			
			//Draw vertical guides
			gEnter.selectAll("line.guide")
			.data(data.data)
			.enter().append("line")
			.attr("x1", X)
			.attr("x2", X)
			.attr("y1", 0)
			.attr("y2", height-margin.bottom-margin.top)
			.style("stroke", "#ccc");
			
			//Bounding lines
			//Draw vertical guides
			
			gEnter.selectAll("line.bounding")
			.data([xScale.rangeExtent()[0] , xScale.rangeExtent()[1]])
			.enter().append("line")
			.attr("x1", String)
			.attr("x2", String)
			.attr("y1", 0)
			.attr("y2", height-margin.bottom-margin.top)
			.style("stroke", "#ccc");
			
			
			//Draw horizontal guides
			gEnter.selectAll("line.scale")
			.data(yScale.ticks(10))
			.enter().append("line")
			.attr("x1", 0)
			.attr("x2", xScale.rangeExtent()[1] )
			.attr("y1", function(d) { return yScale(d) })
			.attr("y2", function(d) { return yScale(d) })
			.style("stroke", "#ccc");
			
			
			//x Labels
			gEnter.selectAll("text.xlabels")
			.data(data.data)
			.enter().append("text")
			.attr("x", X)
			.attr("y", yScale(0))
			.attr("dy", "+10px") // vertical-align: middle
			.attr("text-anchor", "middle")
			.attr("class", "xlabels")
			.text(function(d,i) { return d.id; });
			
			
			//scale labels
			gEnter.selectAll("text.scale")
			.data(yScale.ticks(10))
			.enter().append("text")
			.attr("x", "-1em")
			.attr("text-anchor", "end")
			.attr("dy", "0.5em")
			.attr("class", "scale")
			.attr("y", function(d) { return yScale(d) })
			.text(String);
			
			
		  	
		  	// Add bars
		  	
		  	baroffset = d3.round((xScale.rangeBand())/6*2)
		  	gEnter.selectAll("rect.bar")
		  	.data(data.data)
		  	.enter().append("rect")
		  	.attr("class", "bar")
		  	.attr("x", function(d,i) { return X(d,i)-baroffset})
		  	.attr("y", Y)
		  	.attr("height", function(d,i) { return height - margin.top - margin.bottom - Y(d,i)} )
		  	.attr("width", d3.round((xScale.rangeBand()*2)/3))
		  	
		  	 //Add labels
		  	 
		  	 
		  	 gEnter.selectAll("text.barlabel")
		  	 .data(data.data)
		  	 .enter().append("text")
		  	 .attr("class", "barlabel")
		  	 .attr("x", function(d,i) { return X(d,i)})
		  	 .attr("y", Y)
		  	 .attr("dy", "1.2em")
		  	 .attr("text-anchor", "middle")
		  	 .text(yValue);		  	 
		    
		});
	}

	// The x-accessor for the path generator
	function X(d, i) {
		return xScale(i)+(xScale.rangeBand()/2);
	}
	
	// The y-accessor for the path generator
	function Y(d) {
		return yScale(d.fields[yTitle]);
	}
	
	chart.margin = function(_) {
		if (!arguments.length) return margin;
		margin = _;
		return chart;
	};
	
	chart.width = function(_) {
		if (!arguments.length) return width;
		width = _;
		return chart;
	};
	
	chart.height = function(_) {
		if (!arguments.length) return height;
		height = _;
		return chart;
	};
	
	chart.x = function(_) {
		if (!arguments.length) return xValue;
		xValue = _;
		return chart;
	};
	
	chart.y = function(_) {
		if (!arguments.length) return yValue;
		yValue = _;
		return chart;
	};

  return chart;
}

function ScatterPlot() {
  var margin = {top: 40, right: 40, bottom: 60, left: 40},
      width = 760,
      height = 400,
      xValue = function(d) { return d.fields[xTitle]; },
      yValue = function(d) { return d.fields[yTitle]; },
      xScale = d3.scale.linear(),
      yScale = d3.scale.linear(),
      line = d3.svg.line().x(X).y(Y),
      yTitle = "",
      xTitle = "";

	function chart(selection) {
		selection.each(function(data) {
			//Only one series is supported
			data = data[0];
			
			//Extract graph data
			xTitle = data.fields[0];
			yTitle = data.fields[1];
					
			yScale 
			.domain([0, d3.max(data.data, yValue)])
			.rangeRound([height - margin.top - margin.bottom, 0])
			.nice();
			
			xScale 
			.domain([0, d3.max(data.data, xValue)])
			.rangeRound([0, width - 2*margin.right - margin.left])
			.nice();
		  
		  	// Create the svg element
		    var svg = d3.select(this).append('svg');
		   
		  	// Update the outer dimensions.
		 	svg.attr("width", width)
		    .attr("height", height);
			
			svg.append("rect").attr("x",0)
			.attr("y",0)
			.attr("width", width)
			.attr("height", height)
			.attr("class", "chartcontainer");
			
		  	// Otherwise, create the skeletal chart.
		  	var gChart = svg.append("g");
		  	gChart.attr("x", 0)
		  	.attr("y", 0)
		  	.attr("transform", "translate("+margin.left+",0)");
		  	
		  	var gEnter = gChart.append("g");
		  	var gLabels = gChart.append("g");
		  	
		  	gEnter
		  		.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
		  	
			//Draw markers and extras			
			
			
			
			//Y Label
			gLabels.append("text")
			.attr("transform", "rotate(-90 0 0) translate(-"+height/2+",0)")
			.text(yTitle)
			.classed("title", true);
			
			
			//X Label
			gLabels.append("text")
			.attr("x", ((width-margin.left-margin.right)/2))
			.attr("text-anchor", "middle")
			.attr("y", height - margin.bottom/3)
			.text(xTitle)
			.classed("title", true);
			
			//Draw vertical guides
			gEnter.selectAll("line.guide")
			.data(xScale.ticks(20))
			.enter().append("line")
			.attr("x1", xScale)
			.attr("x2", xScale)
			.attr("y1", 0)
			.attr("y2", height-margin.bottom-margin.top)
			.style("stroke", "#ccc");
			
			//Draw horizontal guides
			gEnter.selectAll("line.scale")
			.data(yScale.ticks(20))
			.enter().append("line")
			.attr("x1", 0)
			.attr("x2", width - 2*margin.right - margin.left)
			.attr("y1", yScale)
			.attr("y2", yScale)
			.style("stroke", "#ccc");
			
			
			//x Labels
			gEnter.selectAll("text.xlabels")
			.data(xScale.ticks(20))
			.enter().append("text")
			.attr("x", xScale)
			.attr("y", yScale(0))
			.attr("dy", "+10px") // vertical-align: middle
			.attr("text-anchor", "middle")
			.attr("class", "xlabels")
			.text(String);
			
			
			//scale labels
			gEnter.selectAll("text.scale")
			.data(yScale.ticks(20))
			.enter().append("text")
			.attr("x", "-1em")
			.attr("text-anchor", "end")
			.attr("dy", "0.5em")
			.attr("class", "scale")
			.attr("y", yScale)
			.text(String);
			
			function drawValueLabel(d,i){
				dx = xValue(d)
				dy = yValue(d)
				
				xoff = xScale(dx)-20
				yoff = yScale(dy)-40 < margin.top ? yScale(dy)+20 : yScale(dy)-20
				
				gEnter.select("text.valueLabel")
				.text(d.id+" ("+dx.toFixed(2)+","+dy.toFixed(2)+")")
				.transition()
				.attr("x", xoff )
				.attr("y",  yoff);
				
				gEnter.selectAll("circle.marker")
				.transition()
				.style("stroke", "none");
				
				d3.select(this)
				.transition()
				.style("stroke", "black")
				.style("stroke-width", 2);
				
				
				gEnter.selectAll("line.lineindy")
				.transition()
				.attr("y1", height-margin.bottom-margin.top)
				.remove();
				
				gEnter.append("line")
				.attr("class", "lineindy")
				.attr("x1", xScale(dx))
				.attr("x2", xScale(dx))
				
				.attr("y2", height-margin.bottom-margin.top)
				.attr("y1", height-margin.bottom-margin.top)
				.transition()
				.attr("y1", yScale(dy)+6)


				gEnter.selectAll("line.lineindx")
				.transition()
				.attr("x2", 0)
				.remove();
				
				gEnter.append("line")
				.attr("class", "lineindx")
				.attr("y2", yScale(dy))
				.attr("y1", yScale(dy))
				
				.attr("x1", 0)
				.attr("x2", 0)
				
				.transition()
				.attr("x2", xScale(dx)-6)
				
				d3.event.stopImmediatePropagation();
			}
			
			function clearSelection(d,i) {
				
				gEnter.select("text.valueLabel")
				.transition()
				.attr("x", -50 )
				.attr("y",  -50);
				
				gEnter.selectAll("circle.marker")
				.transition()
				.style("stroke", "none");
				
				
				gEnter.selectAll("line.lineindy")
				.transition()
				.attr("y1", height-margin.bottom-margin.top)
				.remove();
				
				gEnter.selectAll("line.lineindx")
				.transition()
				.attr("x2", 0)
				.remove();
				
			}
			
			svg.on("click", clearSelection);
			
		  	//Add circles
		  	gEnter.selectAll("circle.marker")
		  	.data(data.data, function(d) { return d.id; })
		  	.enter().append("circle")
		  	.attr("class", "marker")
		  	.attr("cx", X)
		  	.attr("r", "5px")
		  	.attr("cy", Y)
		  	.on("click", drawValueLabel);
		  	
		  	//Relocatable label
		  	gEnter.append("text")
		  		.classed("valueLabel", true)
		  		.attr("x",0)
		  		.attr("y",0)
		  		.style("text-anchor", "end")
		  		.text("");
		});
	}

	// The x-accessor for the path generator
	function X(d, i) {
		return xScale(xValue(d));
	}
	
	// The y-accessor for the path generator
	function Y(d) {
		return yScale(yValue(d));
	}
	
	chart.margin = function(_) {
		if (!arguments.length) return margin;
		margin = _;
		return chart;
	};
	
	chart.width = function(_) {
		if (!arguments.length) return width;
		width = _;
		return chart;
	};
	
	chart.height = function(_) {
		if (!arguments.length) return height;
		height = _;
		return chart;
	};
	
	chart.x = function(_) {
		if (!arguments.length) return xValue;
		xValue = _;
		return chart;
	};
	
	chart.y = function(_) {
		if (!arguments.length) return yValue;
		yValue = _;
		return chart;
	};

  return chart;
}